package org.swirrel.example;

import java.awt.Dimension;
import static java.awt.BorderLayout.*;
import java.awt.FlowLayout;
import java.util.Date;
import javax.swing.BorderFactory;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import javax.swing.JTree;
import javax.swing.ListSelectionModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.swirrel.annotation.ActionPerformed;
import org.swirrel.annotation.ContentsChanged;
import org.swirrel.annotation.FocusGained;
import org.swirrel.annotation.FocusLost;
import org.swirrel.annotation.IntervalAdded;
import org.swirrel.annotation.IntervalRemoved;
import org.swirrel.annotation.KeyPressed;
import org.swirrel.annotation.KeyReleased;
import org.swirrel.annotation.KeyTyped;
import org.swirrel.annotation.MouseClicked;
import org.swirrel.annotation.MouseDragged;
import org.swirrel.annotation.MouseEntered;
import org.swirrel.annotation.MouseExited;
import org.swirrel.annotation.MouseMoved;
import org.swirrel.annotation.MousePressed;
import org.swirrel.annotation.MouseReleased;
import org.swirrel.annotation.MouseWheelMoved;
import org.swirrel.annotation.StateChanged;
import org.swirrel.annotation.TreeNodesChanged;
import org.swirrel.annotation.TreeNodesInserted;
import org.swirrel.annotation.TreeNodesRemoved;
import org.swirrel.annotation.TreeStructureChanged;
import org.swirrel.annotation.ValueChanged;
import org.swirrel.component.SwFrame;
import javax.swing.JTable;
import org.swirrel.annotation.AdjustmentValueChanged;
import org.swirrel.annotation.CaretUpdate;
import org.swirrel.annotation.ChangeUpdate;
import org.swirrel.annotation.ColumnAdded;
import org.swirrel.annotation.ColumnMarginChanged;
import org.swirrel.annotation.ColumnMoved;
import org.swirrel.annotation.ColumnRemoved;
import org.swirrel.annotation.ColumnSelectionChanged;
import org.swirrel.annotation.ComponentAdded;
import org.swirrel.annotation.ComponentHidden;
import org.swirrel.annotation.ComponentMoved;
import org.swirrel.annotation.ComponentRemoved;
import org.swirrel.annotation.ComponentResized;
import org.swirrel.annotation.ComponentShown;
import org.swirrel.annotation.InsertUpdate;
import org.swirrel.annotation.RemoveUpdate;
import org.swirrel.annotation.UndoableEditHappened;

/**
 * <p>Title: Swirrel</p>
 *
 * <p>Description: </p>
 *
 * <p>Copyright: Copyright (c) 2009</p>
 *
 * <p>Company: </p>
 *
 * @author Daniel Gronau
 * @version 0.1
 */
public class TabbedExampleSwFrame
    extends SwFrame {

  @ComponentHidden("call")
  @ComponentMoved("call")
  @ComponentResized("call")
  @ComponentShown("call")
  private static JFrame frame;

  private final JTextArea area = new JTextArea(8, 60);
  @StateChanged("clearTextArea")
  private final JTabbedPane tabs = new JTabbedPane();

  public TabbedExampleSwFrame() {
    super("TabbedExampleSwFrame");
    setSize(800, 600);
    setLocation(50, 50);
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    getContentPane().add(getTabs(), CENTER);
    getContentPane().add(new JScrollPane(area), SOUTH);
    setVisible(true);
  }

  private JComponent getTabs() {
    tabs.add("ActionListener", getActionPanel());
    tabs.add("FocusListener", getFocusPanel());
    tabs.add("JTextField", getKeyPanel());
    tabs.add("Mouse...Listener", getMousePanel());
    tabs.add("JList", getJListPanel());
    tabs.add("JTree", getJTreePanel());
    tabs.add("JTable", getJTablePanel());
    tabs.add("JScrollBar", getJScrollBarPanel());
    tabs.add("Container", getContainerPanel());
    return tabs;
  }

  @ActionPerformed("call")
  private final JButton button = new JButton("Click me!");

  private JComponent getActionPanel() {
    JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    panel.add(button);
    return panel;
  }

  @FocusGained("call")
  @FocusLost("call")
  private final JTextField textfield1 = new JTextField(30);

  @FocusGained("call")
  @FocusLost("call")
  private final JTextField textfield2 = new JTextField(30);

  private JComponent getFocusPanel() {
    JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    panel.add(textfield1);
    panel.add(textfield2);
    return panel;
  }

  @KeyPressed("call")
  @KeyReleased("call")
  @KeyTyped("call")
  @InsertUpdate("call")
  @RemoveUpdate("call")
  @ChangeUpdate("call")
  @UndoableEditHappened("call")
  @CaretUpdate("call")
  private final JTextField textfield3 = new JTextField(30);

  private JComponent getKeyPanel() {
    JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    panel.add(textfield3);
    return panel;
  }

  @MouseClicked("call")
  @MouseDragged("call")
  @MouseEntered("call")
  @MouseExited("call")
  @MouseMoved("call")
  @MousePressed("call")
  @MouseReleased("call")
  @MouseWheelMoved("call")
  private final JLabel mouseLabel = new JLabel("    Play with the mouse!");

  private JComponent getMousePanel() {
    JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    mouseLabel.setBorder(BorderFactory.createEtchedBorder());
    mouseLabel.setPreferredSize(new Dimension(200, 100));
    panel.add(mouseLabel);
    return panel;
  }

  @ValueChanged("call")
  @ContentsChanged("call")
  @IntervalAdded("call")
  @IntervalRemoved("call")
  private final JList jList = new JList(new DefaultListModel());

  @ActionPerformed("addListEntry")
  private final JButton addEntryButton = new JButton("Add Entry");

  @ActionPerformed("removeListEntry")
  private final JButton removeEntryButton = new JButton("Remove Entry");

  private JComponent getJListPanel() {
    JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    jList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    DefaultListModel model = (DefaultListModel) jList.getModel();
    for (String s : new String[] {"one", "two", "three", "four", "five"}) {
      model.add(model.size(), s);
    }
    JScrollPane sp = new JScrollPane(jList);
    sp.setPreferredSize(new Dimension(150, 150));
    panel.add(sp);
    panel.add(addEntryButton);
    panel.add(removeEntryButton);
    return panel;
  }

  private void addListEntry() {
    DefaultListModel model = ( (DefaultListModel) (jList.getModel()));
    model.add(model.size(), "Entry" + System.currentTimeMillis() % 1000);
  }

  private void removeListEntry() {
    DefaultListModel model = ( (DefaultListModel) (jList.getModel()));
    int[] indexes = jList.getSelectedIndices();
    for (int i = indexes.length - 1; i >= 0; i--) {
      model.remove(indexes[i]);
    }
  }

  @ValueChanged("call")
  @TreeNodesChanged("call")
  @TreeNodesInserted("call")
  @TreeNodesRemoved("call")
  @TreeStructureChanged("call")
  private final JTree jTree = new JTree(new DefaultTreeModel(new
      DefaultMutableTreeNode("root")));

  @ActionPerformed("addTreeEntry")
  private final JButton addTreeEntryButton = new JButton("Add Entry");

  @ActionPerformed("removeTreeEntry")
  private final JButton removeTreeEntryButton = new JButton("Remove Entry");

  private JComponent getJTreePanel() {
    JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    jTree.setEditable(true);
    jTree.getSelectionModel().setSelectionMode(TreeSelectionModel.
                                               SINGLE_TREE_SELECTION);

    JScrollPane sp = new JScrollPane(jTree);
    sp.setPreferredSize(new Dimension(150, 150));
    panel.add(sp);
    panel.add(addTreeEntryButton);
    panel.add(removeTreeEntryButton);
    return panel;
  }

  private void addTreeEntry() {
    TreePath parentPath = jTree.getSelectionPath();
    DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) ( (parentPath == null)
        ? jTree.getModel().getRoot()
        : parentPath.getLastPathComponent());

    DefaultMutableTreeNode childNode =
        new DefaultMutableTreeNode("Entry" + System.currentTimeMillis() % 1000);
    ( (DefaultTreeModel) jTree.getModel()).insertNodeInto(childNode, parentNode,
        parentNode.getChildCount());
    jTree.scrollPathToVisible(new TreePath(childNode.getPath()));
  }

  private void removeTreeEntry() {
    TreePath path = jTree.getSelectionPath();
    if (path != null) {
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.
          getLastPathComponent();
      if (!node.isRoot()) {
        ( (DefaultTreeModel) jTree.getModel()).removeNodeFromParent(node);
      }
    }
  }

  private static final Object[][] tableData = {
      {
      "January", "February", "March"}, {
      "April", "May", "June"}, {
      "July", "August", "September"}, {
      "October", "November", "December"}
  };
  @ValueChanged("call")
  @ColumnAdded("call")
  @ColumnMarginChanged("call")
  @ColumnMoved("call")
  @ColumnRemoved("call")
  @ColumnSelectionChanged("call")
  private final JTable jTable = new JTable(tableData,
                                           new Object[] {"1", "2", "3"});

  private JComponent getJTablePanel() {
    JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
    JScrollPane sp = new JScrollPane(jTable);
    jTable.getColumnModel().setColumnSelectionAllowed(true);
    sp.setPreferredSize(new Dimension(250, 150));
    panel.add(sp);
    return panel;
  }

  @AdjustmentValueChanged("call")
  private final JScrollBar jScrollBar = new JScrollBar(JScrollBar.HORIZONTAL);

  private JComponent getJScrollBarPanel() {
     JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
     jScrollBar.setPreferredSize(new Dimension(250, 20));
     panel.add(jScrollBar);
     return panel;
  }

  @ComponentAdded("call")
  @ComponentRemoved("call")
  private final JPanel containerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));

  @ActionPerformed("addLabel")
  private final JButton containerAddButton = new JButton("Add");
  @ActionPerformed("removeLabel")
  private final JButton containerRemoveButton = new JButton("Remove");

  private JComponent getContainerPanel() {
     JPanel panel = new JPanel(new FlowLayout(FlowLayout.CENTER));
     containerPanel.setPreferredSize(new Dimension(500, 300));
     containerPanel.setBorder(BorderFactory.createEtchedBorder());
     panel.add(containerPanel);
     panel.add(containerAddButton);
     panel.add(containerRemoveButton);
     return panel;
  }

  private void addLabel() {
     containerPanel.add(new JLabel(new Date().toString()));
     containerPanel.invalidate();
     containerPanel.validate();
     containerPanel.repaint();
  }
  private void removeLabel() {
      if(containerPanel.getComponentCount() > 0) {
        containerPanel.remove(containerPanel.getComponentCount() - 1);
        containerPanel.invalidate();
        containerPanel.validate();
        containerPanel.repaint();
      }
  }

  public void call(Object obj) {
    area.append(obj.toString() + "\n");
  }

  public void clearTextArea() {
    area.setText("");
  }

  public static void main(String ...args) {
    frame = new TabbedExampleSwFrame();
  }

}
